﻿/*
Copyright (c) 2010, hiSoft
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the hiSoft nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE HISOFT AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL HISOFT BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;

namespace Orchard.Test.Library
{
    public class ContentItemHelper : UIHelperBase
    {
        public ContentItemHelper(TestLibrary settings) : base(settings) { }

        private int GetActionIndexByText(int contentItemIndex, string actionText)
        {
            var actionCount = (int)selenium.GetXpathCount(String.Format("{0}[{1}]/div/div[2]/a", ContentItemsLocator, contentItemIndex));
            for (int i = 1; i <= actionCount; i++)
            {
                if (selenium.GetText(String.Format("{0}[{1}]/div/div[2]/a[{2}]", ContentItemsLocator, contentItemIndex, i)) == actionText)
                {
                    return i;
                }
            }
            return 0;
        }

        public void ManageContents()
        {
            if (!selenium.GetLocation().Contains("/Admin/Contents/List"))
            {
                selenium.Open("/Admin/Contents/List");
            }
        }

        public int GetContentItemsCount()
        {
            ManageContents();
            int contentItemsCount = 0;
            if (selenium.IsElementPresent(ContentItemsLocator))
            {
                contentItemsCount = (int)selenium.GetXpathCount(ContentItemsLocator);
            }
            else if (selenium.IsElementPresent("//fieldset[@class='contentItems bulk-items']/div/ul/li"))
            {
                contentItemsCount = (int)selenium.GetXpathCount("//fieldset[@class='contentItems bulk-items']/div/ul/li");
            }
            return contentItemsCount;
        }

        public int GetContentItemIndexOnManageContents(ContentItem contentItem)
        {
           return GetContentItemIndexOnManageContents(contentItem.Title);
        }

        public int GetContentItemIndexOnManageContents(string contentItemTitle)
        {
            var count = GetContentItemsCount();
            var index = 1;
            for (; index <= count; ++index)
            {
                string path = String.Format("{0}[{1}]/div/div/h3/a", ContentItemsLocator, index);
                var text = selenium.GetText(path);
                if (String.CompareOrdinal(contentItemTitle, text) == 0)
                    break;
            }

            if (index > count)
                throw new CaseFailureException(String.Format("Can't find content item {0} in Manage Content page!", contentItemTitle));

            return index;
        }

        public bool IsContentItemPresent(ContentItem contentItem)
        {
            ManageContents();
            return selenium.IsElementPresent(String.Format("link={0}", contentItem.Title));
        }

        public void DoActionToContentItem(ContentItem contentItem, ContentItemAction action)
        {
            DoActionToContentItem(contentItem.Title, action);
        }

        public void DoActionToContentItem(string contentItemTitle, ContentItemAction action)
        {
            int contentItemIndex = GetContentItemIndexOnManageContents(contentItemTitle);
            string actionText = null;
            switch (action)
            {
                case ContentItemAction.Edit:
                    actionText = "Edit";
                    break;
                case ContentItemAction.Publish:
                    actionText = "Publish";
                    break;
                case ContentItemAction.PublishDraft:
                    actionText = "Publish Draft";
                    break;
                case ContentItemAction.Delete:
                    actionText = "Delete";
                    break;
                case ContentItemAction.Unpublish:
                    actionText = "Unpublish";
                    break;
                case ContentItemAction.ShowContainedItems:
                    actionText = "Contained Items";
                    break;
                case ContentItemAction.View:
                    actionText = "View";
                    break;
            }
            int actionIndex = GetActionIndexByText(contentItemIndex, actionText);
            ClickAndWait(String.Format("{0}[{1}]/div/div[2]/a[{2}]", ContentItemsLocator, contentItemIndex, actionIndex));
        }

        public void DoSelectActionToContentItem(ContentItem contentItem, ContentItemAction action)
        {
            int index = GetContentItemIndexOnManageContents(contentItem);
            selenium.Check(String.Format("{0}[{1}]/div/div/input", ContentItemsLocator, index));
            switch (action)
            {
                case ContentItemAction.Publish:
                    selenium.Select("publishActions", "label=Publish Now");
                    break;
                case ContentItemAction.Unpublish:
                    selenium.Select("publishActions", "label=Unpublish");
                    break;
                case ContentItemAction.Delete:
                    selenium.Select("publishActions", "label=Delete");
                    break;
                default:
                    break;
            }
            ClickAndWait("//button[@name='submit.BulkEdit']");
        }

        public void EditContentItem(ContentItem contentItem)
        {
            DoActionToContentItem(contentItem, ContentItemAction.Edit);
            Submit();
        }   

        public void FilterContentsByContentType(string typeName)
        {
            selenium.Open(String.Format("/Admin/Contents/List/{0}",typeName)); 
        }

        public void OrderContentsByCondition(string typeName, OrderByCondition condition)
        {
            string conditionText = null;
            switch (condition)
            {
                case OrderByCondition.RecentlyCreated:
                    conditionText = "Created";
                    break;

                case OrderByCondition.RecentlyModified:
                    conditionText = "Modified";
                    break;

                case OrderByCondition.RecentlyPublished:
                    conditionText = "Published";
                    break;
                default:
                    break;
            }
            selenium.Open(String.Format("/Admin/Contents/List/{0}?Options.OrderBy={1}", typeName, conditionText));
        }

        public void DisplayContentItem(ContentItem contentItem)
        {
            selenium.Open(String.Format("/Contents/Item/Display/{0}", contentItem.Id));
        }    

        public void PreviewContentItem(ContentItem contentItem, int? version)
        {
            if (version == null)
            {
                selenium.Open(String.Format("/Contents/Item/Preview/{0}", contentItem.Id));
            }
            else
            {
                selenium.Open(String.Format("/Contents/Item/Preview/{0}?version={1}", contentItem.Id, version));
            }
        }

        public void ShowOrphanedContentItems()
        {
            selenium.Open("/Admin/Lists/Orphaned");
        }

        //the following function is same with OrderContentsByCondition
        public void FilterContentItems(string showOption_ContentType,string orderByOption)
        {
            ManageContents();
            if (!string.IsNullOrEmpty(showOption_ContentType)) selenium.Select("filterResults", "label=" + showOption_ContentType);
            if (!string.IsNullOrEmpty(orderByOption)) selenium.Select("orderResults", "label=" + orderByOption);
            selenium.Click("submit.Filter");
        }

        public bool IsOrderCorrectly(string orderByCondition)
        {
            int itemCount=(int)selenium.GetXpathCount(ListItemListLocator);
            bool result=true;
            if(itemCount>1)
            {
             switch (orderByCondition)
             {
                case("recently modified"):
                    string modifiedDate="";
                    string modifiedDateNext="";
                    for(int i=1;i<=itemCount; i++)
                    {
                      modifiedDate=selenium.GetText(string.Format("{0}[{1}]/div/div/div/ul[2]/li[1]",ListItemListLocator,i));
                        modifiedDate=modifiedDate.Substring(modifiedDate.IndexOf("on")+2);
                        DateTime dt=DateTime.Parse(modifiedDate);
                        modifiedDateNext=selenium.GetText(string.Format("{0}[{1}]/div/div/div/ul[2]/li[1]",ListItemListLocator,i+1));
                        modifiedDateNext=modifiedDate.Substring(modifiedDate.IndexOf("on")+2);
                        DateTime dtNext=DateTime.Parse(modifiedDateNext);
                        if (dt.CompareTo(dtNext)>=1)
                      {
                          result=true;
                      }
                      else 
                        {
                          result= false; 
                        }
                    }
                    break;
                       
                    
            }
            }
            return result;
        }

        public string GetPublishDateTime_ViewPage()
        {
            return selenium.GetText("//div[@class='metadata']/div[@class='published']");
        }

    }

    public abstract class ContentItem
    {
        public string Title { get; protected set; }

        public string Permalink { get; protected set; }

        public string Owner { get; protected set; }

        public int Id { get; set; }
    }

    public enum OrderByCondition
    {
        RecentlyCreated,
        RecentlyModified,
        RecentlyPublished
    }

    public enum ContentItemAction
    {
        View,
        Unpublish,
        Publish,
        PublishDraft,
        Edit,
        Delete,
        ShowContainedItems,
        NoAction
    }

    public abstract class ContentItemSettings
    {
        public string Title { get; set; }

        public string Permalink { get; set; }

        public bool SetAsHomePage { get; set; }

        public string Owner { get; set; }

        public int Id { get; set; }
    }
}
